/**
 * 手风琴效果实现
 * 封装功能，优化代码结构
 */

// 页面加载完成后执行
window.onload = function() {
  // 初始化手风琴
  const accordion = new Accordion({
    containerSelector: '.container', // 手风琴容器
    itemSelector: '.item',           // 菜单项
    titleSelector: 'h2',             // 菜单标题
    contentSelector: '.sub-menu',    // 菜单内容
    animationDuration: 300,          // 动画持续时间(ms)
    singleExpand: true               // 是否只允许同时展开一个
  });
  
  // 初始化所有菜单
  accordion.init();
};

/**
 * 手风琴类
 * @param {Object} options - 配置选项
 */
function Accordion(options) {
  // 配置选项
  this.options = options;
  // 动画计时器Map
  this.animationTimers = new Map();
  // 所有菜单项
  this.items = [];
  
  /**
   * 初始化手风琴
   */
  this.init = function() {
    // 获取所有菜单项
    const container = document.querySelector(this.options.containerSelector);
    this.items = container.querySelectorAll(this.options.itemSelector);
    
    // 初始化每个菜单项
    this.items.forEach(item => this.initItem(item));
    
    // 绑定点击事件
    this.bindEvents();
  };
  
  /**
   * 初始化单个菜单项
   * @param {HTMLElement} item - 菜单项元素
   */
  this.initItem = function(item) {
    const subMenu = item.querySelector(this.options.contentSelector);
    
    // 设置初始高度为0，并隐藏溢出部分
    // subMenu.style.height = '0px';
    // subMenu.style.overflow = 'hidden';
    
    // 计算并保存子菜单真实高度
    this.calculateHeight(subMenu);
    
    // 设置初始状态为"已关闭"
    item.setAttribute('data-state', 'closed');
  };
  
  /**
   * 计算子菜单的真实高度并保存
   * @param {HTMLElement} subMenu - 子菜单元素
   */
  this.calculateHeight = function(subMenu) {
    const subItems = subMenu.querySelectorAll('li');
    // 每个子项高度30px（行高）
    subMenu.setAttribute('data-height', subItems.length * 30 + 'px');
  };
  
  /**
   * 绑定菜单项点击事件
   */
  this.bindEvents = function() {
    const self = this;
    
    this.items.forEach(item => {
      const title = item.querySelector(this.options.titleSelector);
      
      title.addEventListener('click', function() {
        self.toggleItem(item);
      });
    });
  };
  
  /**
   * 切换菜单项状态
   * @param {HTMLElement} item - 菜单项元素
   */
  this.toggleItem = function(item) {
    const currentState = item.getAttribute('data-state');
    
    // 根据当前状态执行对应操作
    switch(currentState) {
      case 'closed':
        // 关闭状态 -> 打开
        this.openItem(item);
        break;
      case 'open':
        // 打开状态 -> 关闭
        this.closeItem(item);
        break;
      case 'opening':
        // 正在打开 -> 立即停止并关闭
        this.reverseOpening(item);
        break;
      case 'closing':
        // 正在关闭 -> 立即停止并打开
        this.reverseClosing(item);
        break;
    }
  };
  
  /**
   * 打开菜单项
   * @param {HTMLElement} item - 菜单项元素
   */
  this.openItem = function(item) {
    // 如果配置为单个展开，则关闭其他所有项
    if (this.options.singleExpand) {
      this.closeOtherItems(item);
    }
    
    const subMenu = item.querySelector(this.options.contentSelector);
    const title = item.querySelector(this.options.titleSelector);
    
    // 设置为打开中状态
    item.setAttribute('data-state', 'opening');
    
    // 获取目标高度
    const targetHeight = parseFloat(subMenu.getAttribute('data-height'));
    
    // 执行打开动画
    this.animate({
      element: subMenu,
      from: parseFloat(subMenu.style.height) || 0,
      to: targetHeight,
      duration: this.options.animationDuration,
      onUpdate: function(value) {
        subMenu.style.height = value + 'px';
      },
      onComplete: function() {
        item.setAttribute('data-state', 'open');
        title.classList.add('active');
      }
    });
  };
  
  /**
   * 关闭菜单项
   * @param {HTMLElement} item - 菜单项元素
   */
  this.closeItem = function(item) {
    const subMenu = item.querySelector(this.options.contentSelector);
    const title = item.querySelector(this.options.titleSelector);
    
    // 设置为关闭中状态
    item.setAttribute('data-state', 'closing');
    
    // 执行关闭动画
    this.animate({
      element: subMenu,
      from: parseFloat(subMenu.style.height),
      to: 0,
      duration: this.options.animationDuration,
      onUpdate: function(value) {
        subMenu.style.height = value + 'px';
      },
      onComplete: function() {
        item.setAttribute('data-state', 'closed');
        title.classList.remove('active');
      }
    });
  };
  
  /**
   * 在正在打开状态时反转为关闭
   * @param {HTMLElement} item - 菜单项元素
   */
  this.reverseOpening = function(item) {
    const subMenu = item.querySelector(this.options.contentSelector);
    const title = item.querySelector(this.options.titleSelector);
    
    // 获取当前高度
    const currentHeight = parseFloat(subMenu.style.height);
    
    // 取消当前动画
    this.cancelAnimation(subMenu);
    
    // 设置为关闭中状态
    item.setAttribute('data-state', 'closing');
    
    // 执行关闭动画，从当前高度到0
    this.animate({
      element: subMenu,
      from: currentHeight,
      to: 0,
      duration: this.options.animationDuration * (currentHeight / parseFloat(subMenu.getAttribute('data-height'))),
      onUpdate: function(value) {
        subMenu.style.height = value + 'px';
      },
      onComplete: function() {
        item.setAttribute('data-state', 'closed');
        title.classList.remove('active');
      }
    });
  };
  
  /**
   * 在正在关闭状态时反转为打开
   * @param {HTMLElement} item - 菜单项元素
   */
  this.reverseClosing = function(item) {
    const subMenu = item.querySelector(this.options.contentSelector);
    const title = item.querySelector(this.options.titleSelector);
    
    // 获取当前高度和目标高度
    const currentHeight = parseFloat(subMenu.style.height);
    const targetHeight = parseFloat(subMenu.getAttribute('data-height'));
    
    // 取消当前动画
    this.cancelAnimation(subMenu);
    
    // 设置为打开中状态
    item.setAttribute('data-state', 'opening');
    
    // 执行打开动画，从当前高度到目标高度
    this.animate({
      element: subMenu,
      from: currentHeight,
      to: targetHeight,
      duration: this.options.animationDuration * ((targetHeight - currentHeight) / targetHeight),
      onUpdate: function(value) {
        subMenu.style.height = value + 'px';
      },
      onComplete: function() {
        item.setAttribute('data-state', 'open');
        title.classList.add('active');
      }
    });
  };
  
  /**
   * 关闭除指定项外的所有菜单项
   * @param {HTMLElement} exceptItem - 不关闭的菜单项
   */
  this.closeOtherItems = function(exceptItem) {
    const self = this;
    
    this.items.forEach(item => {
      if (item !== exceptItem) {
        const state = item.getAttribute('data-state');
        if (state !== 'closed') {
          self.closeItem(item);
        }
      }
    });
  };
  
  /**
   * 执行动画
   * @param {Object} options - 动画选项
   */
  this.animate = function(options) {
    // 取消元素当前正在进行的动画
    this.cancelAnimation(options.element);
    
    const from = options.from;
    const to = options.to;
    const duration = options.duration || 1000;
    const gap = 15; // 帧间隔时间
    const times = Math.floor(duration / gap);
    const dis = (to - from) / times;
    
    let currentTime = 0;
    let currentValue = from;
    
    // 创建新动画
    const timerId = setInterval(() => {
      currentTime++;
      if (currentTime >= times) {
        currentValue = to;
        options.onUpdate && options.onUpdate(currentValue);
        clearInterval(timerId);
        this.animationTimers.delete(options.element);
        options.onComplete && options.onComplete();
        return;
      }
      currentValue += dis;
      options.onUpdate && options.onUpdate(currentValue);
    }, gap);
    
    // 存储计时器ID
    this.animationTimers.set(options.element, timerId);
  };
  
  /**
   * 取消元素当前正在进行的动画
   * @param {HTMLElement} element - 要停止动画的元素
   */
  this.cancelAnimation = function(element) {
    if (this.animationTimers.has(element)) {
      clearInterval(this.animationTimers.get(element));
      this.animationTimers.delete(element);
    }
  };
}
